package cate.game.role.res.call.nature;

import cate.common.table.call.row.CallBaseRow;
import cate.common.table.d.GDHeroCall;
import cate.common.table.d.GDNotice;
import cate.common.table.d.GDObj;
import cate.common.table.d.GDOperation;
import cate.common.table.item.hero.row.HeroBaseRow;
import cate.game.chat.ChatContentParam;
import cate.game.event.hero.HeroStarChangeEvent;
import cate.game.res.*;
import cate.game.role.Role;
import cate.game.role.bag.hero.Hero;
import cate.game.role.res.call.CallBasePO;
import cate.game.role.res.call.CallManager;
import cate.game.role.res.call.CallTool;
import cate.game.role.res.call.base.*;
import cate.game.role.res.call.msg.CallNatureExchangeInfoResp;
import cate.game.train.hero.msg.HeroBaseUpdateResp;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@NoteClass(value = "食神召唤")
public class CallNatureCallPO extends CallBasePO implements ICallExe {

  @NoteField(value = "召唤-置换原消耗")
  public CostSelect costSelect;

  @NoteField(value = "召唤-置换后id")
  public int exchangeId;

  @NoteField(value = "许愿当天次数")
  public int times;

  @Override
  public void initialize(Role role, CallTool tool) {
    super.initialize(role, tool);
    role.getRes().callPO.register(getMode(), this);
  }

  public CallNatureCallPO() {
  }

  @Override
  public void onEnter() {
    super.onEnter();
    Hero hero = exchangeHeroGet();
    if (hero == null) {
      role.getGame().notice.message(role, "英雄不存在");
      clearExchange();
    }
  }

  private void clearExchange() {
    this.costSelect = null;
    this.exchangeId = 0;
  }

  @Override
  protected void handlerRegister() {
    Set<Integer> typeSet = role.getGame().table.call.base.getModeAllType(getMode());
    typeSet.forEach(type -> CallManager.register(type, CallManager.callNatureBaseHandler));
    CallManager.register(GDHeroCall.Mode.NATURE_SUB_EXCHANGE, CallManager.callNatureExchangeHandler);
  }

  @Override
  protected byte getMode() {
    return GDHeroCall.Mode.NATURE;
  }

  @Override
  protected void noticeUpdate(Role role) {
    this.role.getRes().callPO.noticeCallDataUpdate();
  }

  @Override
  public void handleResult(Role role, CallProcessData processData, ICallHandler handler, CallBasePO po) {
    if (!handler.calcResult(role, processData, po).ok()) {
      return;
    }

    if (handler instanceof CallNatureExchangeHandler) {
      this.costSelect = processData.cs;
      this.exchangeId = processData.result.get(0).getRow(role).heroId;
      sendExchangeMsg(role, processData);
      if (processData.base.callType == GDHeroCall.Mode.NATURE_SUB_EXCHANGE) {
        role.getHistory().action.heroReplace();
      }
      return;
    }
    updatePO(role, processData, po);
    MixRes fragments = new MixRes();
    processData.reward.add(role);
    for (CallResult result : processData.result) {
      fragments.addList(new MixRes(result.getRow(role).rewardStr));
      fragments.addList(new MixRes(result.getRow(role).fragmentStr));
    }
    fragments.add(role, true, GDOperation.NATURE_CALL_EXE);
    if (processData.base.callType < GDHeroCall.Mode.NATURE_POINTS_EXCHANGE_START) {
      tool.FragNoticeLamp(role, processData);
    }

    tool.sendFragCallResp(role, processData, po);
    this.noticeUpdate(role);
    if (processData.base.callType == GDHeroCall.Mode.NATURE_SUB_EXCHANGE) {
      role.getHistory().action.heroReplace();
    }
  }

  private void updatePO(Role role, CallProcessData processData, CallBasePO po) {
    if (getSubMode(processData.base) == GDHeroCall.Mode.NATURE_SUB_BASE) {
      this.times += processData.getMaxTime();
    }
    tool.updatePo(role, processData, po);
  }

  /**
   * 发送置换状态信息
   *
   * @param role
   * @param processData
   */
  private void sendExchangeMsg(Role role, CallProcessData processData) {
    Hero hero = exchangeHeroGet(role, processData);
    if (hero != null) {
      noticeReplace(role, hero.uid, exchangeId, true, 0);
    }
  }

  private Hero exchangeHeroGet() {
    if (this.costSelect == null) {
      return null;
    }

    for (Option option : this.costSelect.options) {
      if (option.type != GDObj.Type.HERO) {
        continue;
      }
      for (String uid : option.uidList) {
        return role.getBag().hero.getItem(uid);
      }
    }

    return null;
  }


  private Hero exchangeHeroGet(Role role, CallProcessData processData) {
    if (this.costSelect == null) {
      return null;
    }

    for (Option option : this.costSelect.options) {
      if (option.type != GDObj.Type.HERO) {
        continue;
      }
      for (String uid : option.uidList) {
        return role.getBag().hero.getItem(uid);
      }
    }

    return null;
  }

  @Override
  public CallNatureCallPO onGotPO(Role role) {
    return role.getRes().callPO.nature;
  }

  @Override
  public void onDaySpan(boolean silence) {
    super.onDaySpan(silence);
    this.times = 0;
  }

  /**
   * 执行置换或者取消
   *
   * @param confirm
   */
  public void exeExchange(boolean confirm) {
    Hero hero = exchangeHeroGet();

    if (hero == null) {
      role.getGame().notice.message(role, "英雄不存在");
      return;
    }

    if (exchangeId == 0) {
      role.getGame().notice.message(role, "请先置换英雄");
      return;
    }

    if (hero.lock.manual) {
      role.getGame().notice.message(role, "英雄已上锁");
      return;
    } else if (hero.lock.heroFight) {
      role.getGame().notice.message(role, "英雄已上阵");
      return;
    } else if (hero.lock.heroPendant) {
      role.getGame().notice.message(role, "英雄在聚灵树中");
      return;
    } else if (hero.lock.heroShare) {
      role.getGame().notice.message(role, "英雄在世界树中");
      return;
    }
    if (hero.getTpl(role.getGame()).star != 5) {
      role.getGame().notice.message(role, "该英雄无法置换");
      return;
    }
    if (confirm) {
      HeroBaseRow heroBaseRow = role.getGame().table.hero.base.get(exchangeId);
      if (heroBaseRow == null) {
        role.getGame().notice.message(role, "英雄不存在");
        return;
      }
      RewardShow rewardShow = hero.offAllEquip(role);
      rewardShow.merge(hero.offAllRune(role));
      if (!rewardShow.isEmpty()) {
        role.getGame().notice.dialog(role, rewardShow);
      }
      logger.info("{}将英雄{}置换成了{}", role.getBase().name, hero.tid, exchangeId);
      hero.tid = exchangeId;
      //置换的英雄资质大于等于九十五弹出跑马灯
      if (heroBaseRow.zizhi >= 95) {
        lamp(exchangeId);
      }
      HeroBaseUpdateResp.send(role, hero);
      publishEvent(role, new HeroStarChangeEvent(role, hero.uid, heroBaseRow.star, 0, heroBaseRow.camp));
    } else {
      logger.info("{}取消将英雄{}置换成{}", role.getBase().name, hero.tid, exchangeId);
    }
    hero.lock.releaseReplaceLock(role);
    this.exchangeId = 0;
    this.costSelect = null;
    noticeRelease(role, hero.uid, confirm ? 1 : 2);
  }

  private void lamp(int heroId) {
    List<ChatContentParam> params = new ArrayList<>();
    params.add(ChatContentParam.c(role.getBase().name));
    params.add(ChatContentParam.c(ChatContentParam.TYPE_HERO_ID, heroId));
    role.getGame().notice.lampOnline(role, GDNotice.TextId.HERO_EXCHANGE, params);
  }

  public void noticeRelease(Role role, String heroUid, int status) {
    noticeReplace(role, heroUid, 0, false, status);
  }

  private void noticeReplace(Role role, String heroUid, int replaceTid, boolean replaceLock, int status) {
    new CallNatureExchangeInfoResp(heroUid, replaceTid, replaceLock, status).sendNow(role);
  }

  public void release(String heroUid) {
    this.exchangeId = 0;
    this.costSelect = null;
    noticeRelease(role, heroUid, 0);
  }

  public int getSubMode(CallBaseRow base) {
    if (base.callType < GDHeroCall.Mode.NATURE_POINTS_EXCHANGE_START) {
      return GDHeroCall.Mode.NATURE_SUB_BASE;
    } else if (base.callType < GDHeroCall.Mode.NATURE_SUB_EXCHANGE) {
      return GDHeroCall.Mode.NATURE_SUB_POINT;
    } else {
      return GDHeroCall.Mode.NATURE_SUB_EXCHANGE;
    }
  }
}
